package com.nova.scenic.projectlibs.util.exec;

import java.io.*;

import com.nova.scenic.projectlibs.util.debug.MyLog;

public class JavaShellUtil {
    private static final boolean SHOW_DEBUG_MSG = true;
    private static final String TAG = "JavaShellUtil";
    private LogClassThread errorGobbler;
    private LogClassThread outputGobbler;
    private Process process;

    private OnGetExecuteLogListener mGetLogListener;

    boolean debugMode = false;
    public void executeLocalCmd(String cmdStr) {
		executeLocalCmd(cmdStr, true,null);
	}

    public void setDebugMode(boolean debugMode){
        this.debugMode = debugMode;
    }

	public Process executeLocalCmd(String cmdStr, boolean executeProgressWait,OutputStream outputStream) {
        MyLog.i("JavaShellUtil","cmdStr is " + cmdStr);
        try {
			Runtime rt = Runtime.getRuntime();

            String osName = System.getProperties().getProperty("os.name");
			if (osName.startsWith("Win")) {
				process = rt.exec(new String[] { "cmd", "/c", cmdStr }, null);
			} else if (osName.startsWith("Li")) {
                String runTime = System.getProperties().getProperty("java.runtime.name");

                if(runTime.startsWith("Android")){
                    process = rt.exec(cmdStr);
                }else {
                    try {
                        //android 下不可以这样使用
                        process = rt.exec(new String[] { "/bin/sh", "-c", cmdStr }, null);
                    } catch (Exception e) {
                        MyLog.e(TAG,e.toString());
                        e.printStackTrace();
                    }
                }
			}

			// any error message?
			errorGobbler = new LogClassThread(process.getErrorStream(), "warning");

			// any output?
			outputGobbler = new LogClassThread(process.getInputStream(), "OUTPUT",outputStream);

			// kick them off
			errorGobbler.start();
			outputGobbler.start();
			// any error???
			if(executeProgressWait){
				int exitVal = process.waitFor();
				if (SHOW_DEBUG_MSG) {
					System.out.println("ExitValue: " + exitVal);
				}
			}
			return process;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return null;
	}

    public void setOnGetExecuteLogListener(OnGetExecuteLogListener l) {
        mGetLogListener = l;
    }

    public void release(){
        outputGobbler.interrupt();
        errorGobbler.interrupt();
        process.destroy();
    }

	public static void log(String line) {
//		System.out.println(line);
	}

    public interface OnGetExecuteLogListener{
        void onGetLineLog(String line);
    }

    class LogClassThread extends Thread {
        InputStream is;
        String type;
        OutputStream outputStream;
        boolean isStop = false;


        public LogClassThread(InputStream is, String type) {
            this.is = is;
            this.type = type;
            isStop = false;
        }

        public LogClassThread(InputStream is, String type,OutputStream outputStream) {
            this(is, type);
            this.outputStream = outputStream;
        }

        @Override
        public void interrupt() {
            isStop = true;
            super.interrupt();
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        public void run() {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;
            try {
                while (!isStop && (line = reader.readLine()) != null ) {
                    if(debugMode){
                        System.out.println(type + " " + line);
                    }

                    if(mGetLogListener != null){
                        mGetLogListener.onGetLineLog(line);
                    }

                    if(type.equals("warning")){

                    }else {
                        if(outputStream != null){
                            try {
                                outputStream.write(line.getBytes());
                                outputStream.write("\n".getBytes());
                                outputStream.flush();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }else{
                            System.out.println(line);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}